﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Reflection;
using System.Management;

namespace Inspector
{
    public class InspectorUtils
    {
        private static Dictionary<string, string> environmentVariables;

        public static Dictionary<string, string> EnvironmentVariables
        {
            get { return InspectorUtils.environmentVariables==null?environmentVariables=GetEnvironmentVariables():environmentVariables; }            
        }
        
        public static Dictionary<string,string> GetEnvironmentVariables()
        {
            Dictionary<string, string> toReturn = new Dictionary<string, string>();
            foreach (var item in Environment.GetEnvironmentVariables().Keys.Cast<string>())
            {
                toReturn.Add(item, Environment.GetEnvironmentVariable(item));
            }
            return toReturn;
        }

        private static Dictionary<string, string> extendedEnvironmentVariables;

        public static Dictionary<string, string> ExtendedEnvironmentVariables
        {
            get { return InspectorUtils.extendedEnvironmentVariables == null ? extendedEnvironmentVariables = GetExtendedEnvironmentVariables() : extendedEnvironmentVariables; }
        }
        
        public static Dictionary<string, string> GetExtendedEnvironmentVariables()
        {
            return GetProperties(typeof(Environment));
        }

        private static Dictionary<string, string> environmentSpecialFolders;

        public static Dictionary<string, string> EnvironmentSpecialFolders
        {
            get { return InspectorUtils.environmentSpecialFolders == null ? environmentSpecialFolders = GetEnvironmentSpecialFolders() : environmentSpecialFolders; }
        }
        
        public static Dictionary<string, string> GetEnvironmentSpecialFolders()
        {
            Dictionary<string, string> toReturn = new Dictionary<string, string>();
            var names = Enum.GetNames(typeof(Environment.SpecialFolder));
            foreach (var item in names)
            {
                toReturn.Add(item,Environment.GetFolderPath((Environment.SpecialFolder)Enum.Parse(typeof(Environment.SpecialFolder),item)));
            }
            return toReturn;
        }

        public static Dictionary<string,string> GetEnvironmentDrives(string drive)
        {
            return GetProperties(new DriveInfo(drive));
        }

        private static Dictionary<DriveInfo, List<string>> drivesFolders;

        public static Dictionary<DriveInfo, List<string>> DrivesFolders
        {
            get { return InspectorUtils.drivesFolders == null ? drivesFolders = GetDrivesFolders() : drivesFolders; }
        }        

        public static Dictionary<DriveInfo, List<string>> GetDrivesFolders(string filter="")
        {
            Dictionary<DriveInfo, List<string>> toReturn = new Dictionary<DriveInfo, List<string>>();
            var type = typeof(DriveInfo);
            foreach (var item in Environment.GetLogicalDrives().Where(p=> filter=="" || p.ToLower().Contains(filter)))
            {
                var drive = new DriveInfo(item);
                toReturn.Add(drive, EnumerateDirectories(item,new List<string>()));
            }
            return toReturn;
        }

        private static Dictionary<string, string> GetProperties(object obj)
        {            
            var props = new Dictionary<string, string>();
            var type = obj.GetType();
            foreach (var prop in type.GetProperties())
            {
                try
                {
                    props.Add(prop.Name, prop.GetValue(obj, null).ToString());
                }
                catch (Exception)
                {

                }
            }
            return props;
        }

        private static Dictionary<string, string> GetProperties(Type type) {
            var props = new Dictionary<string, string>();

            foreach (var prop in type.GetProperties(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly))
            {
                try
                {
                    props.Add(prop.Name, prop.GetValue(type, null).ToString());
                }
                catch (Exception)
                {

                }
            }
            return props;
        }

        private static List<string> EnumerateDirectories(string start,List<string> dirs)
        {
            try
            {
                dirs.Add(start);
                foreach (string d in Directory.GetDirectories(start))
                {
                    EnumerateDirectories(d, dirs);
                }
            }
            catch { }
            return dirs;
        }

        private static Dictionary<string, Dictionary<string, string>> machineProperties = new Dictionary<string, Dictionary<string, string>>();

        public static Dictionary<string, Dictionary<string, string>> MachineProperties
        {
            get { return InspectorUtils.machineProperties; }            
        }

        public static Dictionary<string, string> GetMachineProperties(string key)
        {
            if (machineProperties.ContainsKey(key)) return machineProperties[key];
            ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from " + key);
            Dictionary<string, string> toReturn = new Dictionary<string, string>();
            try
            {
                foreach (ManagementObject share in searcher.Get())
                {
                    if (share.Properties.Count <= 0)
                    {
                        continue;
                    }

                    foreach (PropertyData PC in share.Properties)
                    {
                        if (PC.Value != null && PC.Value.ToString() != "")
                        {
                            toReturn.Add(PC.Name, PC.Value.ToString());
                        }
                    }
                }
            }
            catch { }
            machineProperties.Add(key, toReturn);
            return toReturn;
        }
    }
}